// ==UserScript== // @name 【开发】华医网公共课考试|使用说明:http://doc.zhanyc.cn/pages/hywggkks/ // @namespace https://doc.zhanyc.cn/ // @icon https://js.zhanyc.cn/img/js-logo.svg // @version 1.0 // @description 脚本付费才能使用!一次付费永久使用!付费才能保证脚本好用、持续更新、省心省力。接各类平台代挂、脚本开发工作,VX:zhanyc_cn,备用:zhanfengkuo // @author zfk // @include *://*91huayi.com* // @grant GM_getValue // @grant GM_setValue // @grant GM_addStyle // @grant GM_deleteValue // @grant GM_xmlhttpRequest // @grant GM_setClipboard // @grant GM_registerMenuCommand // @grant GM_getResourceURL // @grant GM_addValueChangeListener // @grant GM_removeValueChangeListener // @grant GM_getResourceText // @grant window.close // @run-at document-start // @require https://m.zhanyc.cn/jquery-2.2.4.min.js // @require https://m.zhanyc.cn/layerjs-gm-with-css.js // @include *://m.zhanyc.cn/* // @connect m.zhanyc.cn // @connect localhost // @connect js.zhanyc.cn // @antifeature payment // @license Creative Commons // ==/UserScript== (function () { // @run-at document-start // http://code.jquery.com/jquery-2.1.1.min.js let $jq = $; unsafeWindow.$jq = $; let baseConfig = { project: { id: "1857789578690170881", version: "202411162244", }, url: { login: "https://m.zhanyc.cn/simp/index.html", base: "https://m.zhanyc.cn/api", resource: "https://js.zhanyc.cn", // login: "http://localhost:9604/simp/index.html", // base: "http://localhost:8202/api", }, }; let docUrl = "http://doc.zhanyc.cn/pages/hywggkks/"; let ignoreAuth = true; let isCheckVersion = false // 是否是定制开发 定制开发的无需授权 不显示文档、我的信息菜单。请将这个放到tamper.js的中间位置 // let isDZKF = true; // 是否启用版本更新检测 isCheckVersion = true let isDev = true; isDev = false; ignoreAuth = false; let zfk = Object.assign(baseConfig, { setting: { // tjjl: "推荐购买脚本,返佣40%", tjjl: "推荐购买脚本,返佣40%", version: { version: "202411221611", body: `
懒得写了~
`, }, }, config: { maxComment: 100, }, pageData: { userNameIndex: null, closeTipsIndex: null, confirmRunIndex: null, confirmRunZIndex: 19991018, waitTime: 0, index: { list: null, }, video: { index: null, }, }, async init() { console.log("%c init", "background:rgb(0,0,0);color:#fff"); var lockResolver; zfk.setHook && zfk.setHook() if (navigator && navigator.locks && navigator.locks.request) { const promise = new Promise((res) => { lockResolver = res; }); navigator.locks.request("unique_lock_name", { mode: "shared" }, () => { return promise; }); } zfk.addStyle(); let alertBak = unsafeWindow.alert unsafeWindow.alert = function (msg) { if (msg == '失败!本次考试报名人数已经上限,请待考核部门发布新的考务信息后再报名') { layer.alert(msg); } else { alertBak(msg) } }; // 新版本 if (location.href.indexOf("loginSuccess.html?yh=") != -1) { console.log( "%c loginSuccess.html?yh", "background:rgb(255,0,0);color:#fff" ); zfk.page_yhwelcome(); } let run = true; run = await zfk.checkVersion(); if (run) zfk.firstRun(); }, async runByUrl(url) { if (top == window) { zfk.page_top() } if (url.includes("XXXXXXXXXXXX")) { zfk.page_video(); } else if (url.includes("course_public_exam")) { await zfk.setUserName() zfk.page_course_public_exam(); } else if (url.includes("public_exam.aspx?")) { await zfk.setUserName2() zfk.page_public_exam(); } else if (url.includes("SSSSSSSSSSSSS")) { await zfk.setUserName(); zfk.page_list(); } else if (url.includes("SSSSSSSSSSS")) { zfk.page_courseDetail(); } }, findQA(batchRes, title) { let qa = batchRes.find(a => a.fullTitle == title); if (!qa) qa = batchRes.find(a => zfk.simpleHtml(a.fullTitle) == zfk.simpleHtml(title)); if (!qa) qa = batchRes.find(a => zfk.simpleText(a.fullTitle) == zfk.simpleText(title)); return qa }, checkQATxt(txt, txt2) { return qa }, async page_course_public_exam() { await zfk.gmAuthDownScore("1f05e59ba1dd45f399ef7cd4ba77c7ad") }, async collPageQa() { if ($(`[id^='gvQuestion_question']:visible`).length == 0) { zfk.tipsMsg("当前功能需要在答题页面使用,当前没检测到题目") return } let qaArr = [] $(`[id^='gvQuestion_question']:visible`).each((i, el) => { let title = $(el).text().trim().replace(/^\d+、/, ''); $(el).parents('table:first').next() .find("label") .each((aI, aEl) => { if (!$(aEl).prev().prop("checked")) { return true; } let answer = $(aEl) .text() .replace(/^\w\、/, "") .trim() answer = answer.replace(/^\w\、\s*/, '').trim() qaArr.push({ key: title, value: answer }) }); }); isDev && console.log(qaArr); await zfk.uploadQA(qaArr, 60, "华医网") zfk.tipsMsg("题库导入成功,本次导入数量:" + qaArr.length) }, async openAutoSet() { layer.prompt({ title: "请输入定时交卷延迟时间(单位:分钟)" } , function (value, index, elem) { layer.close(index); zfk.confirmRun(`脚本将会在${value}分钟后自动交卷,请确保所有题目都已经答题完成。如需取消自动交卷,请点击下面【取消执行】按钮`, value * 60 * 1000).then(a => { $(`[name="btn_submit"]`).click() }) }); }, async addSubmitBtn() { $("body").append(`
`); }, async page_public_exam() { console.log("%c page_public_exam", "background:rgb(0,0,0);color:#fff"); await zfk.gmAuthDownScore("1f05e59ba1dd45f399ef7cd4ba77c7ad") await zfk.waitOf(a => $(`[id^='gvQuestion_question']:visible`).length > 0) if (!zfk.isDZKFMode()) { // zfk.addSubmitBtn() } await zfk.waitTimeout(500) let titleArr = []; let config = zfk.getConfig() zfk.tipsMsg("准备查询答案"); $(`[id^='gvQuestion_question']:visible`).each((i, el) => { let title = $(el).text().trim().replace(/^\d+、/, ''); titleArr.push(title); }); isDev && console.log(titleArr); let $elArr = []; let batchRes = await zfk.queryQaFree(titleArr, "华医网", false, null); $(`[id^='gvQuestion_question']:visible`).each((i, el) => { let title = $(el).text().trim().replace(/^\d+、/, ''); let old = zfk.findQA(batchRes, title); if (!old) { if (config.sjdt == '2') return; else { $elArr.push($(el).parents('table:first').next() .find("label").eq(0).click()) return } } let answerStrArr = old.fullAnswer.split("#split#"); $(el).parents('table:first').next() .find("label") .each((aI, aEl) => { let answer = $(aEl) .text() .replace(/^\w\、/, "") .trim() answer = answer.replace(/^\w\、\s*/, '') let has = answerStrArr.find( (a) => a == answer || zfk.isMatchQAText(answer, a) ); if (has) { $elArr.push($(aEl)); } }); }); for (let index = 0; index < $elArr.length; index++) { const $el = $elArr[index]; $el.click(); zfk.tipsMsg("正在答题") await zfk.waitTimeout(100); } zfk.tipsMsg("答题完毕"); if (config.sjdt == '1') { if ($(`[value="下一页"]:visible`).length > 0) { zfk.confirmRun("本页题目答题完毕,1分钟后自动翻页", 10 * 1000).then(a => { $(`[value="下一页"]:visible`).click() }) return } } if ($(`[value="交卷"]:visible`).length > 0 && config.zdjj == '1') { let time = zfk.random(Number(config.zdjj_min) * 60, Number(config.zdjj_max) * 60) zfk.confirmRun(`答题完毕,脚本会在${(time / 60).toFixed(1)}分钟后自动交卷`, time * 1000).then(a => { $(`[name="btn_submit"]`).click() }) } }, async qaUload() { await zfk.gmAuthDownScore("1f05e59ba1dd45f399ef7cd4ba77c7ad") let txt = zfk.pageData.qaTxt; let arr = txt.split('\n').map(a => a.trim()).filter(a => !!a) let qaArr = [] arr.forEach(item => { let arr = item.split('\t').map(a => a.trim()) if (arr.length < 3) { return } let title = arr[0] let answerTxt = arr[1].replace(/(\w)(\.|、)/g, '$1、') let answerArr = answerTxt.split(/(?=[a-zA-Z]\、)/); let options = arr[2].trim().replace(/[^a-zA-Z]/g, '').split('') let relAnswerArr = [] options.forEach(opt => { let curAnswerTxt = answerArr.find(a => a.startsWith(opt + "、")) if (curAnswerTxt) { curAnswerTxt = curAnswerTxt.substring(2) if (curAnswerTxt.endsWith(",")) { curAnswerTxt = curAnswerTxt.substring(0, curAnswerTxt.length - 1) } relAnswerArr.push(curAnswerTxt) } }) qaArr.push({ key: title, value: relAnswerArr.join("#split#"), answerArr, options }) }) console.log(qaArr); zfk.showQaUpdatePreview(qaArr) }, async showQaUpdatePreview(qaArr) { qaArr = qaArr.map(a => ({ key: a.key, value: a.value })) let html = `` qaArr.forEach((item, index) => { html += `
[${index + 1}]${item.key}
` html += `
答案:${item.value}
` }) if (zfk.pageData.showQaUpdatePreview != null) { layer.close(zfk.pageData.showQaUpdatePreview) } html = `
${html}
` zfk.pageData.showQaUpdatePreview = layer.open({ title: '脚本:导入题库预览', type: 1, content: html, area: ['600px', '600px'], btn: ["确认导入", "关闭"], yes: function (index) { zfk.uploadQAConfrim(qaArr) }, btn2() { }, }); }, async uploadQAConfrim(qaArr) { await zfk.gmAuthDownScore("1f05e59ba1dd45f399ef7cd4ba77c7ad") let loadIndex = layer.load() await zfk.uploadQA(qaArr, 60, '华医网') layer.close(loadIndex) zfk.tipsMsg("导入完成,共导入题目数量:" + qaArr.length) }, async openMgConfigTips(waitTime = 0) { return new Promise(async (resolve, reject) => { let curMark = 1 let config = zfk.getConfig() if (config.mg == '1') { zfk.setGMData("openMgConfigTipsMark", curMark) return resolve() } let openMgConfigTipsMark = zfk.getGMData("openMgConfigTipsMark", 0) if (openMgConfigTipsMark != curMark) { await zfk.waitTimeout(waitTime) zfk.confirmMsg("本脚本具有秒过功能,是否需要开启?(仅秒过版本生效)", { btn: ["开启秒过", "1倍速慢放"], fun1(index) { config.mg = '1' zfk.setConfig(config); zfk.alertMsg("秒过开启成功,祝您玩的愉快!【刷新页面后脚本自动执行】") zfk.setGMData("openMgConfigTipsMark", curMark) layer.close(index) }, fun2(index) { config.mg = '2' zfk.setConfig(config); zfk.alertMsg("未开启秒过。如果您后续需要使用秒过,可通过浏览器右上角的[脚本菜单]切换!【刷新页面后脚本自动执行】") zfk.setGMData("openMgConfigTipsMark", curMark) layer.close(index) } }) return reject(); } return resolve() }); }, page_top() { GM_addValueChangeListener('openLjts', function (name, old_value, new_value, remote) { zfk.openLjTips() }) }, firstRun() { if (zfk.isDZKFMode()) { zfk.begin("iamzhankuo"); return; } if (top === window && zfk.getGMData("showDoc", true)) { layer.confirm( "首次使用本脚本?点击下方按钮查看使用说明", { icon: 3, title: "首次使用?", btn: ["查看使用说明", "取消"] }, function (index) { zfk.openDoc(); layer.close(index); zfk.setGMData("showDoc", false); zfk.begin("iamzhankuo"); }, function () { zfk.setGMData("showDoc", false); zfk.begin("iamzhankuo"); } ); } else { } zfk.begin("iamzhankuo"); }, async addMenu() { await zfk.waitOf(a => $("body:visible").length > 0) if ($("#zfkLeftMenuContainer").length > 0) return; GM_addStyle(`#zfkLeftMenuContainer{z-index:9999;position:fixed;left:0;top:40%;color:#fff;box-shadow:0 0 10px #00ffcc,0 0 20px #00ffcc,0 0 30px #00ffcc;animation:glowAnimation 3s infinite alternate;}@keyframes glowAnimation{0%{box-shadow:0 0 10px #00ffcc,0 0 20px #00ffcc,0 0 30px #00ffcc;}20%{box-shadow:0 0 15px #ff66cc,0 0 25px #ff66cc,0 0 35px #ff66cc;}40%{box-shadow:0 0 10px #ffcc33,0 0 20px #ffcc33,0 0 30px #ffcc33;}60%{box-shadow:0 0 15px #66ff66,0 0 25px #66ff66,0 0 35px #66ff66;}80%{box-shadow:0 0 10px #3399ff,0 0 20px #3399ff,0 0 30px #3399ff;}100%{box-shadow:0 0 10px #fffb00,0 0 20px #fffb00,0 0 30px #fffb00;}}#zfkLeftMenuContainer .zfkLeftMenuStep{position:absolute;background:#3498db;width:max-content;top:-35px;display:block;padding:6px}#zfkLeftMenuContainer .zfkLeftMenu{background:rgba(0,0,0,0.4);border-radius:0 4px 4px 0;padding:6px}#zfkLeftMenuContainer .zfkLeftMenu:hover .zfkLeftMenuBtn-titile{width:auto}#zfkLeftMenuContainer .zfkLeftMenu .zfkLeftMenuBtn-titile{cursor:pointer;word-wrap:break-word;width:1em;display:inline-block}#zfkLeftMenuContainer .zfkLeftMenu .zfkLeftMenuBtnUl{display:none;margin:0 -6px;box-sizing:border-box}#zfkLeftMenuContainer .zfkLeftMenu .zfkLeftMenuBtnUl li{list-style:none;color:#fff !important;cursor:pointer;padding:6px}#zfkLeftMenuContainer .zfkLeftMenu .zfkLeftMenuBtnUl li:hover{background:#000}#zfkLeftMenuContainer .zfkLeftMenu .zfkLeftMenuBtnUl li::before{content:"+ "}#zfkIp51Config{padding:10px}`); $(`
菜单
`).appendTo("body"); $(".zfkLeftMenu").hover( () => { $(".zfkLeftMenuBtnUl").show(); }, () => { $(".zfkLeftMenuBtnUl").hide(); } ); }, async begin(key) { if (key != "iamzhankuo") { return; } if (window === top) { zfk.addMenu() zfk.registerMenuCommand(); } // let lastUrl =location.href; // setInterval(async () => { // if (lastUrl != location.href) { // lastUrl = location.href; // zfk.runByUrl(location.href); // } // }, 500); zfk.runByUrl(location.href); }, setSkip(event, courseId, skip) { event.stopPropagation() $(".skipContainer").remove(); var sikpList = zfk.getGMData("skipList", []); if (skip) { sikpList.push(courseId); zfk.setGMData("skipList", sikpList); } else { zfk.setGMData( "skipList", sikpList.filter((a) => a != courseId) ); } layer.msg("操作成功"); zfk.setSkipBtn(); }, setSkipBtn() { var sikpList = zfk.getGMData("skipList", []); $(".zfk-skipContainer").remove() $("#currentCourseDiv .course").each((i, el) => { let courseId = $(el).attr("courseid"); let $btnContainer = $(el) if (sikpList.includes(courseId)) { $btnContainer.after( `
` ); } else { $btnContainer.after( `
` ); } }); }, async page_list() { console.log("%c page_list", "background:rgb(0,0,0);color:#fff"); await zfk.gmAuthDownScore("1f05e59ba1dd45f399ef7cd4ba77c7ad"); await zfk.waitOf((a) => $(".view-item").length > 0); await zfk.waitTimeout(1000) let $el = null; let userData = await zfk.getUserData() $(".view-item").each((i, el) => { // let jd = Number( // $(el).find(".el-progress__text").text().trim().replace("%", "") // ); // let jd = Number( // $(el).find('.progress').text().replace(/[^0-9\.]/g, '') // ); // if (jd < 100) { // $el = $(el); // return false; // } /** 课程名称判断 let title = $(el).find('h3').text().trim() if (!userData.video.includes(title)) { $el = $(el) return false } */ let cId = $(el) .find("a.view-shadow") .attr("href") .replace(/.*\/(\d+)\.mooc/, "$1"); if (!data.includes(cId)) { $el = $(el).find("a.view-shadow"); return false; } }); if ($el == null) { zfk.alertMsg( "学习完成,如果结果有误,请使用`脚本菜单`中的清理缓存功能后再试" ); return; } zfk.setGMData("listUrl", location.href); zfk.confirmRun("3秒后执行下一步", 3000).then((a) => { $el[0].click(); zfk.openLjTips() }); }, async page_list_nextPage() { let old = $(".my_course_item").eq(0).find('.course_name_link').text().trim() if (!$(`[ng-click="nextPage()"]`).is('.disabled')) { $(`[ng-click="nextPage()"]`).click() await zfk.waitOf(a => $(".my_course_item").eq(0).find('.course_name_link').text().trim() != old) await zfk.waitTimeout(500) zfk.page_list() } else { zfk.alertMsg("学习完成") } }, toListPage(tips = true, top = false) { let timeout = 3000; if (!tips) timeout = 0; let _local = location; if (top) _local = top.location; zfk .confirmRun("当前课程已经完成,准备前往下一个课程", timeout) .then((a) => { let url = zfk.getGMData("listUrl", null); if (url == null) { zfk.alertMsg( "请手动前往列表页面,让脚本自动从列表页面打开视频播放页面,否则无法完成自动换课" ); return; } _local.href = url; }); }, async setVideoFinish() { let title = $(".play_title").text().trim() let userData = await zfk.getUserData() userData.video.push(title) zfk.setUserData(userData) }, async page_videoTop() { console.log("%c page_videoParent", "background:rgb(0,0,0);color:#fff"); zfk.closeWaitConfrimWin() GM_addValueChangeListener( "close", function (name, old_value, new_value, remote) { window.close(); } ); GM_addValueChangeListener( "updateTitle", function (name, old_value, new_value, remote) { $("title").text(new_value) } ); }, async setCourseFinish() { return new Promise(async (resolve, reject) => { let courseName = $(".course-info .title").text() let userData = await zfk.getUserData() if (!userData.finishCourseArr.includes(courseName)) { userData.finishCourseArr.push(courseName) } let config = zfk.getConfig() let item = config.courseNameMap.find(a => a.name1 == courseName || a.name2 == courseName) if (item) { if (!userData.finishCourseArr.includes(item.name1)) { userData.finishCourseArr.push(item.name1) } if (!userData.finishCourseArr.includes(item.name2)) { userData.finishCourseArr.push(item.name2) } } await zfk.setUserData(userData) return resolve(); }); }, async page_courseDetail() { console.log("%c page_courseDetail", "background:rgb(0,0,0);color:#fff"); GM_addValueChangeListener('videoFinish', function (name, old_value, new_value, remote) { location.reload() }) await zfk.waitOf(a => $(`a[onclick^="startLesson("]`).length > 0) await zfk.waitTimeout(500) let $el = null $(`a[onclick^="startLesson("]`).each((i, el) => { if ($(el).parents('td:first').next().attr('title') == '已完成') { return true } $el = $(el) return false }) if ($el == null) { zfk.confirmRun("学习完成,前往列表页面").then((a) => { let url = zfk.getGMData("listUrl", "/"); location.href = url; }); return; } zfk.setGMData("courseDetailUrl", location.href); zfk.confirmRun("3秒后执行下一步", 3000).then((a) => { $el[0].click(); zfk.openLjTips() }); }, async page_video() { zfk.closeWaitConfrimWin() await zfk.gmAuthDownScore("1f05e59ba1dd45f399ef7cd4ba77c7ad"); console.log("%c page_video", "background:rgb(0,0,0);color:#fff"); let timeout = 2; let lastTime = null; let checkTimeTimesBak = 60; let checkTimeTimes = checkTimeTimesBak; zfk.closeWaitConfrimWin(); if (zfk.pageData.video.index != null) { return; } let config = zfk.getConfig(); let bs = Number(config.bs); setTimeout(async () => { let time = zfk.getCurTime() await zfk.waitTimeout(5000) if (zfk.getCurTime() == time) { zfk.confirmRun("貌似卡主了,3秒后刷新页面").then(a => { location.reload() }) } }, 60 * 1000); zfk.pageData.video.index = setInterval(async () => { try { if (zfk.pageData.waitTime > 0) { zfk.pageData.waitTime -= timeout; return; } if (!zfk.getVideo()) { console.log("%c zfk no video", "background:rgb(0,0,0);color:#fff"); return; } let curTime = zfk.getCurTime(); if (curTime == lastTime) { lastTime = zfk.getCurTime(); checkTimeTimes -= timeout; if (checkTimeTimes <= 0) { checkTimeTimes = checkTimeTimesBak; zfk.confirmRun("貌似卡死了,前往列表页面").then((a) => { location.href = zfk.getGMData("courseDetailUrl", "/"); }); zfk.pageData.waitTime = 10; return; } } else { lastTime = curTime; checkTimeTimes = checkTimeTimesBak; } // if (!location.href.includes("/video?")) { // return; // } // await zfk.setCourseFinish() zfk.getVideo().volume = 0; let title = `进度:${zfk.getCurTime().toFixed(0)}/${zfk.getTotalTime() .toFixed(0)}`; $("title").text(title); // zfk.setGMData("updateTitle", title) console.log("%c video run", "background:rgb(255,0,0);color:#fff"); let $tips = zfk.getElByText( ".layui-layer-content p", "您好,本平台要求实时在线学习,点击按钮,继续学习课程。" ); if ($tips != null) { $tips.parents(".layui-layer").find(".layui-layer-btn0")[0].click(); } let isFinish = await zfk.isPlayFinish(); if (isFinish) { zfk.pageData.waitTime = 15; layer.msg("视频即将结束,等待下一步操作", { time: 10 * 1000 }); // zfk.pageData.waitTime = zfk.getTotalTime() - zfk.getCurTime() + 1; zfk.nextVideo(); clearInterval(zfk.pageData.video.index) zfk.pageData.video.index = null return; } let isPlay = await zfk.videoIsPlay(); if (!isPlay) { if (!isFinish) { zfk.play(); } } // if (zfk.getVideo().playbackRate != bs) { // zfk.getVideo().playbackRate = bs; // } // if (config.mg == '1') { // zfk.setStep(-1) // } } catch (e) { console.error("视频页面定时器出错", e); } }, timeout * 1000); }, nextVideo(waitTime = 10) { layer.msg("视频即将结束,等待下一步操作", { time: 10 * 1000 }); // let $courseList = $("li.kcAllow"); // let index = $courseList.index($("li.kcAllow.selConListItem")); // let length = $courseList.length; // if (index + 1 < length) { // setTimeout(() => { // $courseList.eq(index + 1).click(); // }, 10 * 1000); // } else { // setTimeout(() => { // zfk.confirmRun("准备前往列表页面").then((a) => { // let url = zfk.getGMData("listUrl", "/"); // top.location.href = url; // }); // }, waitTime * 1000); // } setTimeout(() => { // zfk.confirmRun("准备前往列表页面").then((a) => { // let url = zfk.getGMData("listUrl", "/"); // top.location.href = url; // }); top.location.reload(); }, waitTime * 1000); }, async checkVersion() { return new Promise((resolve) => { if (!isCheckVersion) { return resolve(true); } if (isDev) { zfk.delGMData("code"); } if (!top === window || isDev) { return resolve(true); } let lastTime = zfk.getGMData("lastCheckVersionTime", 0); if (zfk.now() - lastTime < 30 * 1000) { console.log("%c 跳过更新检测", "background:rgb(0,0,0);color:#fff"); return resolve(true); } zfk.setGMData("lastCheckVersionTime", zfk.now()) zfk .gmPost("/yh/base/checkVersion", { id: baseConfig.project.id, v1: baseConfig.project.version, v2: zfk.getGMData("version", ""), }) .then( (res) => { if (res.message == "更新脚本") { layer.alert(res.result.msg, function () { top.open(res.result.url); }); } else if (res.message == "更新内容") { zfk.delGMData("code"); location.href = location.href; } return resolve(true); }, (err) => { if (isDev) console.log(err); } ); }); }, localSaveQa(qaArr) { let list = zfk.getGMData("qaList", []); qaArr.forEach((item) => { let old = list.find((a) => a.key == item.key); item.value = item.value.replace(/#split#/g, "|"); if (!old) { list.push(item); } else { old.value = item.value; } }); zfk.setGMData("qaList", list); }, async queryQaLocal(titleArr, offset = "rb", area = ["400px", "400px"]) { return new Promise(async (resolve, reject) => { let list = zfk.getGMData("qaList", []); let batchRes = []; titleArr.forEach((item) => { let has = list.find((a) => a.key == item); if (has) { batchRes.push({ fullTitle: item, fullAnswer: has.value.replace(/\|/gi, "#split#"), }); } }); if (isDev) console.log(batchRes); let html = ""; batchRes.forEach((item) => { html += `
${item.fullTitle }
答案:${item.fullAnswer.replace(/(#split#)/gi, "|")}
`; }); layer.open({ type: 1, closeBtn: "1", shade: 0, title: `题库搜索到${batchRes.length}个相似题目(这里可拖动)`, content: `
${html}
`, offset: offset, area: area, }); return resolve(batchRes); }); }, async queryQaLocal_id(titleArr, offset = "rb", area = ["400px", "400px"]) { return new Promise(async (resolve, reject) => { let list = zfk.getGMData("qaList_id", []); let batchRes = []; titleArr.forEach((item) => { let has = list.find((a) => a.key == item); if (has) { batchRes.push({ fullTitle: item, fullAnswer: has.value.replace(/\|/gi, "#split#"), }); } }); if (isDev) console.log(batchRes); if (offset == null) return resolve(batchRes); let html = ""; batchRes.forEach((item) => { html += `
${item.fullTitle }
答案:${item.fullAnswer.replace(/(#split#)/gi, "|")}
`; }); layer.open({ type: 1, closeBtn: "1", shade: 0, title: `题库搜索到${batchRes.length}个相似题目(这里可拖动)`, content: `
${html}
`, offset: offset, area: area, }); return resolve(batchRes); }); }, play() { zfk.getVideo().volume = 0; setTimeout(() => { zfk.getVideo().play(); }, 200); // }); }, getVideo() { return $("video")[0]; }, setVideoVolume() { try { if (zfk.getVideo().volume != 0) { zfk.getVideo().volume = 0; } } catch (e) { console.error(e); } }, // time负数则是总进度减 否则设置进度 setStep(time) { if (zfk.getVideo()) { if (time >= 0) { zfk.getVideo().currentTime = time; } else { zfk.getVideo().currentTime = zfk.getVideo().duration + time; } } }, isPlayFinish() { try { return ( zfk.getTotalTime() > 0 && zfk.getCurTime() + 5 >= zfk.getTotalTime() ); } catch (e) { return false; } }, getCurTime() { let res = 0; try { res = zfk.getVideo().currentTime; } catch (e) { console.error(e); } return res; }, getTotalTime() { let res = 0; try { res = zfk.getVideo().duration; } catch (e) { console.error(e); } return res; }, // 题库方法 toAnswerOption(no) { // 检查输入是否是单个字母且在 A-Z 范围内 if (/^[a-zA-Z]$/.test(no)) { no = no.toUpperCase(); return no.charCodeAt(0) - 'A'.charCodeAt(0); } else { let arr = [ ["正确", "错误"], ["对", "错"], ]; let opt = no.toUpperCase(); let res = -1; arr.forEach((subArr) => { if (subArr.includes(opt)) { res = subArr.indexOf(opt); return false; } }); return res; } }, // 题库方法 toAnswerOptionNo(index) { return ["A", "B", "C", "D", "E", "F", "G", "H"][index] }, isMatchQAText(txt1, txt2) { return ( txt1 == txt2 || zfk.simpleHtml(txt1).replace(/\s/g, '') == zfk.simpleHtml(txt2).replace(/\s/g, '') || zfk.simpleText(txt1) == zfk.simpleText(txt2) ); }, simpleHtml(html) { html = html.replace(/ ||
|\n|\r/gi, ""); html = html.trim(); if (!html) return html; if (html.startsWith("<") && html.endsWith(">")) { return $(html).text().trim(); } return html.trim(); }, simpleText(text) { return text .replace(/[^\u4e00-\u9fa5a-zA-Z0-9#split#√×]/g, "") .replace(/[的]/g, ""); }, async uploadQA(arr, score = -1, webSite = null) { return new Promise(async (resolve, reject) => { arr = arr.map(a => { if (a.key.length > 499) { a.key = a.key.substring(0, 499) return { key: a.key, value: a.value } } else { return a } }) arr = arr.filter((a) => a.key && a.value && (a.key + '').length < 500); if (arr.length == 0) { return reject("无数据"); } isDev && console.log("uploadQA", arr); let url = "/business/qaQuestionSimple/uploadQaResult" if (zfk.isDZKFMode() || isDev) { url = "/business/common/uploadQaResult" } let res = await zfk.gmAuthPost( url, { list: arr, score, webSite } ); return resolve(res); }); }, async queryQaFree( titleArr, webSite = "", withAllSite = false, offset = "rb", area = ["400px", "400px"] ) { return new Promise(async (resolve, reject) => { let url = "/business/qaQuestionSimple/freeSimpleQueryList" if (zfk.isDZKFMode() || isDev) { url = "/business/common/freeSimpleQueryList" } let arr = [] titleArr.forEach(item => { let title = (item + '') if (item.length > 499) { title = title.substring(0, 499) } arr.push(title) }) let batchRes = await zfk.gmAuthPost( url, { list: arr, webSite: webSite, } ); if (isDev) console.log(batchRes); let count = batchRes.length if (withAllSite) { let titleArr2 = [] titleArr.forEach(title => { let old = batchRes.find( (a) => a.fullTitle == title ); if (!old) { titleArr2.push(title) } }) if (titleArr2.length > 0) { let batchRes2 = await zfk.gmAuthPost( url, { list: titleArr2, webSite: '', } ); batchRes = batchRes.concat(batchRes2) count += batchRes2.length if (isDev) { console.log(batchRes2); console.log(batchRes); } } } zfk.tipsMsg(`共搜索到${count}个题目`) if (!offset) return resolve(batchRes); let html = ""; batchRes.forEach((item) => { html += `
${item.fullTitle }
答案:${item.fullAnswer.replace(/(#split#)/gi, "|")}
`; }); layer.open({ type: 1, closeBtn: "1", shade: 0, title: `题库搜索到${batchRes.length}个相似题目(这里可拖动)`, content: `
${html}
`, offset: offset, area: area, }); return resolve(batchRes); }); }, async videoIsPlay() { return new Promise((resolve) => { try { let curTime = $("video")[0].currentTime; setTimeout(() => { let time1 = $("video")[0].currentTime; let res = time1 > curTime; if (res) { setTimeout(() => { let time2 = $("video")[0].currentTime; let res2 = time2 > time1; resolve(res2); }, 100); } else { return resolve(false); } }, 100); } catch (e) { resolve(false); } }); }, beginMan() { console.log("%c beginMan", "background:rgb(0,0,0);color:#fff"); }, stop() { location.href = location.href; }, openDoc() { if (docUrl) { window.open(docUrl); } else { window.open("http://doc.zhanyc.cn/pages/auth/"); } }, isDZKFMode() { let res = typeof (loadFun) == 'function' && loadFun.toString().includes('var data = res.response;') if (!res) res = typeof isDZKF == "boolean" && !!isDZKF; return res }, async callRegisterMenuCommand(name, fun) { if (!zfk.pageData.menuBtnIndex) { zfk.pageData.menuBtnIndex = 0; } GM_registerMenuCommand(name, fun) await zfk.waitOf(a => $("body:visible").length > 0) await zfk.waitTimeout(500) if ($("#zfkLeftMenuContainer").length > 0) { zfk.pageData.menuBtnIndex++; $("#zfkLeftMenuContainer .zfkLeftMenuBtnUl").append(`
  • ${name}
  • `) $(`#zfkMenuBtn_${zfk.pageData.menuBtnIndex}`).click(function () { fun(); }); } }, openConfig() { let html = `
    自动交卷说明:脚本答题到最后一页之后,会在最小值会最大值之间随机一个时间A,在A分钟后自动交卷
    `; layer.open({ type: "1", title: "设置", content: html, btn: false, area: ["600px", "600px"], }); let config = zfk.getConfig(); zfk.setFormVal(".zfk-form", config); }, registerMenuCommand() { zfk.callRegisterMenuCommand("定时交卷", zfk.openAutoSet); zfk.callRegisterMenuCommand("记录当前答题为标准答案", zfk.collPageQa); zfk.callRegisterMenuCommand("脚本菜单", zfk.openConfig); zfk.callRegisterMenuCommand("清理缓存", zfk.clearResult); zfk.callRegisterMenuCommand("导入题库", zfk.openUploadConfig); if (!zfk.isDZKFMode()) { zfk.callRegisterMenuCommand("使用说明", zfk.openDoc); zfk.callRegisterMenuCommand("我的信息", zfk.myInfo); } zfk.callRegisterMenuCommand("联系作者", zfk.linkAuthor); zfk.callRegisterMenuCommand('版本:' + zfk.setting.version.version, zfk.showVersionAlert); }, // 新版本开始 showVersionAlert(force = true) { let version = zfk.getGMData("showVersionAlert", ""); if (!force && version == zfk.getGMData("version")) return; layer.open({ type: "1", title: `版本号:${zfk.setting.version.version}`, content: zfk.setting.version.body, btn: "我知道了", area: ["600px", "auto"], yes: function (index) { zfk.setGMData("showVersionAlert", zfk.getGMData("version")); layer.close(index); }, }); }, linkAuthor() { window.open("http://doc.zhanyc.cn/contact-me/"); }, logout() { zfk.delGMData("token"); zfk.delGMData("code"); layer.msg("脚本账号已退出"); }, setClip(txt) { GM_setClipboard(txt, "text"); layer.msg("复制成功"); }, async getUserData(userId = null) { return new Promise(async (resolve, reject) => { let acc = zfk.getUserName(); if (zfk.project.isSelf) { let data = await zfk.getUserDataOnline(userId); let res = { id: data.id, acc: data.acc, pwd: data.pwd, name: data.name, video: [], ks: [], }; if (data.list) { let listData = JSON.parse(data.list); res.video = listData.video; res.ks = listData.ks; res.courseList = listData.courseList; } return resolve(res); } let defConfig = { acc: acc, name: acc, video: [], sinishSubArr: [], finishCourseArr: [], finishCoursewareidArr: [], }; let resultList = zfk.getGMData("result", []); let userData = resultList.find((a) => a.acc == acc); if (!userData) { userData = defConfig; resultList.push(userData); zfk.setGMData("result", resultList); // zfk.setGMData("result", resultList); } else { userData = Object.assign(defConfig, userData); } return resolve(userData); }); }, async getUserDataOnline(id = null) { return new Promise(async (resolve, reject) => { return resolve(await zfk.queryCurAcc(id)); }); }, async setUserData(data) { return new Promise(async (resolve, reject) => { if (zfk.project.isSelf) { await zfk.setUserDataOnline(data); return resolve(); } let resultList = zfk.getGMData("result", []); let acc = zfk.getUserName(); let userDataIndex = resultList.findIndex((a) => a.acc == acc); if (userDataIndex == -1) { userData = data; resultList.push(userData); } else { resultList.splice(userDataIndex, 1, data); } zfk.setGMData("result", resultList); return resolve(); }); }, getUserName() { return zfk.getGMData("username", ""); // return zfk.getGMData("username", ""); }, addStyle() { GM_addStyle(` .zfk-btn{background-color:#0fbcf9;color:white;padding:4px 12px;border:none;box-sizing:content-box;font-size:14px;height:20px;border-radius:4px;cursor:pointer;display:inline-block;border:1px solid transparent;white-space:nowrap;user-select:none;text-align:center;vertical-align:middle;}.zfk-btn:hover{opacity:0.8;}.zfk-btn.success{background-color:#38b03f;}.zfk-btn.warning{background-color:#f1a325;}.zfk-btn.info{background-color:#03b8cf;}.zfk-btn.danger{background-color:#ea644a;}.zfk-form-tips{font-size:1.2em;color:red;}.tips{color:red;}.zfk-form{color:#000;}.zfk-form textarea,.zfk-form input[type=text],.zfk-form input[type=number],.zfk-form input[type=password]{border:1px solid #888;border-radius:4px;padding:5px;box-sizing:border-box;}.zfk-form textarea{width:100%;}.zfk-form-item{margin-bottom:10px;}.zfk-form-item > label:first-child{width:7em;text-align:right;display:inline-block;padding-right:5px;margin-right:0;}.zfk-form-item label{margin:0 4px 0 0 !important;}.zfk-form-item input{margin:0 !important;float:none;}.zfk-form-item.block > label:first-child{text-align:left;display:block;width:100%;font-weight:bold;}.text-l{text-align:left !important;}.text-c{text-align:center !important;}.text-r{text-align:right !important;}.p-0{padding:0px !important;}.p-5{padding:5px !important;}.p-10{padding:10px !important;}.p-15{padding:15px !important;}.p-20{padding:20px !important;}.p-t-0{padding-top:0px !important;}.p-t-5{padding-top:5px !important;}.p-t-10{padding-top:10px !important;}.p-t-15{padding-top:15px !important;}.p-t-20{padding-top:20px !important;}.p-b-0{padding-bottom:0px !important;}.p-b-5{padding-bottom:5px !important;}.p-b-10{padding-bottom:10px !important;}.p-b-15{padding-bottom:15px !important;}.p-b-20{padding-bottom:20px !important;}.p-l-0{padding-left:0px !important;}.p-l-5{padding-left:5px !important;}.p-l-10{padding-left:10px !important;}.p-l-15{padding-left:15px !important;}.p-l-20{padding-left:20px !important;}.p-r-0{padding-right:0px !important;}.p-r-5{padding-right:5px !important;}.p-r-10{padding-right:10px !important;}.p-r-15{padding-right:15px !important;}.p-r-20{padding-right:20px !important;}.p-0{padding:0px !important;}.p-5{padding:5px !important;}.p-10{padding:10px !important;}.p-15{padding:15px !important;}.p-20{padding:20px !important;}.m-t-0{margin-top:0px !important;}.m-t-5{margin-top:5px !important;}.m-t-10{margin-top:10px !important;}.m-t-15{margin-top:15px !important;}.m-t-20{margin-top:20px !important;}.m-b-0{margin-bottom:0px !important;}.m-b-5{margin-bottom:5px !important;}.m-b-10{margin-bottom:10px !important;}.m-b-15{margin-bottom:15px !important;}.m-b-20{margin-bottom:20px !important;}.m-l-0{margin-left:0px !important;}.m-l-5{margin-left:5px !important;}.m-l-10{margin-left:10px !important;}.m-l-15{margin-left:15px !important;}.m-l-20{margin-left:20px !important;}.m-r-0{margin-right:0px !important;}.m-r-5{margin-right:5px !important;}.m-r-10{margin-right:10px !important;}.m-r-15{margin-right:15px !important;}.m-r-20{margin-right:20px !important;}.bold{font-weight:bold !important;}.tips-box{padding:10px;border:1px solid red;background-color:#fff0f0;color:red;}.bold{font-weight:bold;}.font-l{font-size:1.2em;}.font-xl{font-size:40px;}.font-l{font-size:25px;}.color-default{color:#ea644a !important;}.color-success{color:#38b03f !important;}.color-warning{color:#f1a325 !important;}.color-danger{color:#ea644a !important;}.bg-default{background-color:#ea644a !important;}.bg-success{background-color:#38b03f !important;}.bg-warning{background-color:#f1a325 !important;}.bg-danger{background-color:#ea644a !important;}.zfk-table{border-collapse:collapse;}.zfk-table thead{background-color:#1abc9c;}.zfk-table td,.zfk-table th{text-align:center;padding:6px;border:1px solid #888;}.zfk-table tr:nth-child(2n){background-color:#f2f2f2;}.zfk-table tr:hover{background-color:#fff799;}.zfk-container *{font-size:17px;}.zfk-hide{display:none !important;}.layui-layer{color:#000;} `); }, // zfk.setGMData("closeLJTS", zfk.now()); openLjTips(tipsAndClose = true, checkUrlBeforeClose = false, timeout = 5000) { let index = layer.open({ type: 1, title: "请确认", offset: "100px", content: `

    已经为你打开下一门课程,如果没有打开窗口,请检查浏览器地址栏右侧是否有拦截提示,请选择【永久允许】或者在浏览器设置中设置本网站【弹出式窗口和重定向】设置为允许

    如下图所示:

    `, }); if (!zfk.pageData.ljtsIndexArr) { zfk.pageData.ljtsIndexArr = [] } zfk.pageData.ljtsIndexArr.push(index) let url = checkUrlBeforeClose ? location.href : ""; if (zfk.pageData.closeTipsIndex != null) return; zfk.pageData.closeTipsIndex = GM_addValueChangeListener( "closeLJTS", function (name, old_value, new_value, remote) { zfk.pageData.ljtsIndexArr.forEach(item => { layer.close(item); }) zfk.pageData.ljtsIndexArr = [] tipsAndClose && zfk.tipsAndClose && zfk.tipsAndClose(url, timeout); } ); }, tipsAndClose(checkUrl, timeout = 5000) { let mark = zfk.now() zfk.pageData.tipsAndCloseMark = mark zfk.confirmRun("准备关闭当前页面,如果不想关闭请点击下面【取消执行】按钮", timeout).then((a) => { if (zfk.pageData.tipsAndCloseMark != mark) { isDev && console.log("页面标识变更,取消关闭窗口"); return } if (!checkUrl || location.href == checkUrl) window.close(); }); }, closeWaitConfrimWin() { zfk.setGMData("closeLJTS", zfk.now()); }, async setUserName_http() { return new Promise(async (resolve, reject) => { // await zfk.waitOf(a => unsafeWindow.$ && unsafeWindow.$().jquery) unsafeWindow.$.post('/****', res => { // let name = JSON.parse(res).currenetUserInfoObj.username let html = res let name = zfk.getElByText($(`${html}`).find('span'), '员工姓名', 'eq', false).parent().text().replace('员工姓名', '').trim() isDev && zfk.tipsMsg('username=' + name) zfk.setGMData('username', name) return resolve(); }) }); }, async setUserName() { return new Promise(async (resolve, reject) => { let username = ""; // let index = layer.load(); await zfk.waitOf((a) => { try { username = $(".name_text").text().trim(); if (username && username != "") { isDev && zfk.tipsMsg('username=' + username) zfk.setGMData("username", username); // zfk.setGMData("username", username); // layer.close(index); return true; } return false } catch (e) { return false } }); return resolve(username); }); }, async setUserName2() { return new Promise(async (resolve, reject) => { let username = ""; // let index = layer.load(); await zfk.waitOf((a) => { try { username = $(".course_title strong").text().trim(); if (username && username != "") { isDev && zfk.tipsMsg('username=' + username) zfk.setGMData("username", username); // zfk.setGMData("username", username); // layer.close(index); return true; } return false } catch (e) { return false } }); return resolve(username); }); }, toUserNamePage() { // 要显示文档按钮、关闭按钮 layer.open({ type: 1, title: "脚本启动失败", content: `
    脚本启动失败,请按脚本说明文档,请在指定的【启动页面】刷新页面后启动脚本
    `, offset: "100px", area: ["400px", "180px"], btn: ["查看脚本说明文档", "关闭"], yes: function (index) { window.open(docUrl) return false } }) return; }, callAuthSuccess() { zfk.setGMData("authSuccess", zfk.now()) }, initBuyAuth() { if (!zfk.pageData.authListnerIndex) { zfk.pageData.authListnerIndex = GM_addValueChangeListener('authSuccess', function (name, old_value, new_value, remote) { if (remote) { layer.close(zfk.pageData.myInfoIndex) layer.close(zfk.pageData.noAuthIndex) layer.open({ type: '1', offset: '100px', title: "脚本授权提示", content: `
    😃授权购买成功,刷新页面后授权生效
    ` }) } }) } if (!zfk.buyAuthFun) { zfk.buyAuthFun = function () { let url = "https://m.zhanyc.cn" isDev && (url = 'http://localhost:3000') window.open(`${url}/yh-auth?i=${baseConfig.project.id}&t=${zfk.getGMData("token")}`) } } }, myInfo() { zfk.initBuyAuth() zfk.gmAuthPost("/yh/user/myInfo").then((res) => { if (isDev) console.log(res); let info = `脚本ID:【${baseConfig.project.id}】 脚本账号昵称:【${res.name}】 脚本账号:【${res.acc}】`; let html = `
    ${zfk.setting.tjjl || "" }
    【${baseConfig.project.id}】
    【${res.name}】
    【${res.acc}】
    `; zfk.pageData.myInfoIndex = layer.open({ type: "1", title: "脚本信息", content: html, area: ["460px", "300px"], offset: "100px", }); }); }, exportResult() { let record = zfk.getGMData("result", []); let text = ""; let titleArr = [ "视频标题", "视频地址", "评论人", "评论时间", "评论内容", "点赞数", "回复数", ]; text += titleArr.join("\t") + "\r\n"; record.forEach((a) => { a.list.forEach((item) => { let itemArr = [ a.title, a.url, item.name, item.time, item.comment, item.likeCount, item.commentCount, ]; text += itemArr.join("\t") + `\r\n`; }); }); zfk.downloadTxt( zfk.dateFormat(new Date(), "yyyyMMddHHmmss") + "导出.txt", text ); }, clearResult() { if (confirm("确认要清空结果数据吗?")) { zfk.setGMData("result", []); // zfk.setGMData("config", []); zfk.delGMData("code", []); layer.msg("清空完成"); } }, openUploadConfig() { let html = `
    👉点击这里下载导入模板
    `; layer.open({ type: "1", title: "设置", content: html, btn: false, area: ["600px", "600px"], }); let config = zfk.getConfig(); zfk.setFormVal(".zfk-form", config); }, saveConfig() { // let config = zfk.getConfig(); var formData = zfk.getFormVal(".zfk-form:first"); isDev && console.log(formData); zfk.setConfig(formData); zfk.pageData.qaTxt = formData.qaTxt zfk.qaUload() layer.msg("保存成功"); }, closeConfig() { layer.closeAll(); }, removeArrEmpty(arr) { let res = []; arr.forEach((item) => { if (!!item && item.trim() != "") { res.push(item); } }); return res; }, confirmRun(msg = "脚本:3秒后执行下一步操作", time = 3000) { return new Promise((resolve, reject) => { let isRun = true; // clearTimeout(zfk.pageData.confirmRunIndex); let confirmRunIndex = layer.open({ type: '1', title: '脚本:是否继续执行?', closeBtn: 0, zIndex: zfk.pageData.confirmRunZIndex++, btn: '取消执行', offset: "100px", content: `
    ${msg}
    `, yes: function (index) { isRun = false; reject(); layer.close(confirmRunIndex); } }); // layer.alert( // msg, // { icon: 3, title: "是否继续?", btn: ["取消执行"], offset: "100px" }, // function (index) { // isRun = false; // reject(); // layer.close(zfk.pageData.confirmRunIndex); // } // ); setTimeout(() => { layer.close(confirmRunIndex); resolve(true); }, time); }); }, waitTimeout(timeout) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(); }, timeout); }); }, /** * 等待目标fun返回true * @param {funcion} fun * @param {string} group 分组标记,相同分组会终止之前的等待方法 * @param {取消标识对象} cancelFlag 用于取消之前的等待方法 * @param {Number} interval 检测频率,默认1000 * @param {Number} timeout 超时时间,默认30 * @returns promise */ waitOf2(fun, group = null, cancelFlag = { cancel: false }, interval = 1000, timeout = 30) { console.log("%c waitOf", "background:rgb(0,0,0);color:#fff"); // 终止之前相同 group 的任务 if (group != null && zfk.pageData["waitOf_" + group]) { zfk.pageData["waitOf_" + group].forEach(i => { isDev && console.log(`清理WaitOf:${group} ${i.index}`); clearInterval(i.index); // 清除之前的定时器 i.cancelFlag.cancel = true; // 标记之前的任务为已取消 }); zfk.pageData["waitOf_" + group] = []; // 清空该 group 的任务列表 } return new Promise((resolve, reject) => { let _timeOut = timeout * 1000; // 如果条件已经满足,立即 resolve if (fun()) { return resolve(); } // 开启新的定时器 let index = setInterval(() => { if (cancelFlag.cancel) { clearInterval(index); return reject(new Error("Operation cancelled")); } if (timeout != -1) { _timeOut -= interval; if (_timeOut < 0) { clearInterval(index); return reject(new Error("Timeout")); } } if (fun()) { clearInterval(index); return resolve(); } }, interval); // 如果 group 存在,将当前定时器和cancelFlag加入对应的 group 列表 if (group != null) { if (!zfk.pageData["waitOf_" + group]) { zfk.pageData["waitOf_" + group] = []; } zfk.pageData["waitOf_" + group].push({ index, cancelFlag }); } }); }, waitOf(fun, interval = 1000, timeout = 30) { console.log("%c waitOf", "background:rgb(0,0,0);color:#fff", fun); return new Promise((resolve, reject) => { let _timeOut = timeout * 1000; try { if (fun()) { return resolve(); } } catch (e) { console.error(e); } let index = setInterval(() => { try { if (timeout != -1) { _timeOut -= interval; if (_timeOut < 0) { clearInterval(index); return reject(); } } if (fun()) { clearInterval(index); return resolve(); } } catch (e) { console.error(e); } }, interval); }); }, toLogin() { top.location.href = zfk.url.login + "?yh=" + window.btoa(encodeURI(top.location.href)); }, getUrlParam(url, name) { if (arguments.length == 1) { name = url; url = window.location; } var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); var r = url.search.substr(1).match(reg); if (r != null) return unescape(r[2]); return ""; }, objectToQueryString(obj) { var queryParams = []; for (var key in obj) { if (obj.hasOwnProperty(key)) { var value = obj[key]; // 如果值为数组,则将其转换为多个参数 if (Array.isArray(value)) { for (var i = 0; i < value.length; i++) { queryParams.push( encodeURIComponent(key) + "=" + encodeURIComponent(value[i]) ); } } else { queryParams.push( encodeURIComponent(key) + "=" + encodeURIComponent(value) ); } } } return queryParams.join("&"); }, parseQueryString(url = window.location.href) { //url参数转对象 url = !url ? window.location.href : url; if (url.indexOf("?") === -1) { return {}; } let search = url[0] === "?" ? url.substr(1) : url.substring(url.lastIndexOf("?") + 1); if (search === "") { return {}; } search = search.split("&"); let query = {}; for (let i = 0; i < search.length; i++) { let pair = search[i].split("="); query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || ""); } return query; }, getAttrName(el, key) { if (el.jquery) el = el.get(0); let propName = Object.keys(el).find((a) => a.startsWith(key)); return propName; }, getAttrNameList(el, key) { if (el.jquery) el = el.get(0); let propName = Object.keys(el).filter((a) => a.startsWith(key)); return propName; }, gmAuthGet(url, data, config = { showErr: true }) { url = zfk.fullUrl(url); if (isDev) console.log("gmGet", url); return new Promise((resolve, reject) => { if (url.indexOf("?") != -1) { for (key in data) { url += `&${key}=${data[key]}`; } } else { let first = true; for (key in data) { url += (first ? "?" : "&") + `${key}=${data[key]}`; first = false; } } let header = {}; if (zfk.getGMData("token", "")) { header["X-Access-Token"] = this.getGMData("token", ""); } GM_xmlhttpRequest({ method: "get", url: url, data: data, headers: header, responseType: "json", onload: function (res) { if (isDev) console.log(res); let data = res.response; try { if (typeof data == 'string') data = JSON.parse(data) } finally { } if (data.code != 200) { if (data.message.indexOf("Token失效") != -1) { zfk.tipsLogin(); } else { if (config.showErr) { layer.alert(data.message); } } reject(data); } else { resolve(data.result); } }, onerror: function (response) { if (isDev) console.log(response); reject(response); }, }); }); }, getAngularScope(selector) { // 获取页面上的元素 var element = document.querySelector(selector); if (!element) { console.error('No element found with the selector: ' + selector); return null; } // 通过AngularJS的工具获取作用域 var scope = angular.element(element).scope(); if (!scope) { console.error('No AngularJS scope found for the element: ' + selector); return null; } return scope; }, tipsLogin( msg = "【未登录】脚本需要付费后才可使用。点击[确定]按钮将前往[脚本账号]的注册/登录页面" ) { layer.open( { type: "1", content: `
    ${msg}
    `, title: "使用脚本前请先登录脚本账号!", offset: "100px", btn: ["去登录", "查看授权说明", "关闭"], yes: function (index) { layer.close(index); zfk.pageData.loginTipsIndex = layer.alert( "已经为您打开登录页面,请留意浏览器窗口" ); zfk.toLogin(); }, btn2: function (index) { // layer.close(index); window.open('https://doc.zhanyc.cn/pages/auth/') return false }, btn2function(index) { layer.close(index); } }, ); }, gmAuthPost(url, data = {}, config = { showErr: true }) { url = zfk.fullUrl(url); if (isDev) console.log("gmPost", url); let header = { "Content-Type": "application/json", }; if (zfk.getGMData("token", "")) { header["X-Access-Token"] = this.getGMData("token", ""); } return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "post", url: url, data: JSON.stringify(data), headers: header, responseType: "json", onload: function (res) { if (isDev) console.log(res); let data = res.response; try { if (typeof data == 'string') data = JSON.parse(data) } finally { } if (data.message.indexOf("Token失效") != -1) { zfk.tipsLogin(); return; } if (data.code != 200) { if (config.showErr) { if (data.message.startsWith("脚本需收费授权使用")) { zfk.initBuyAuth() zfk.pageData.noAuthIndex = layer.open( { type: "1", content: `
    ${data.message}
    `, icon: 3, title: "当前学生账号未授权", offset: "100px", btn: ["去购买授权", "查看授权信息", "查看帮助"], yes: function (index) { zfk.buyAuthFun() }, btn2: function (index) { // layer.close(index); zfk.myInfo(); }, btn3: function (index) { top.open("http://doc.zhanyc.cn/pages/auth/"); return false } }) } else { layer.alert(data.message, { offset: "100px" }, function () { zfk.myInfo(); }); } } reject(data); } else { resolve(data.result); } }, onerror: function (response) { if (isDev) console.log(response); reject(response); }, }); }); }, gmAuthDownScore(id, showErr = true) { return new Promise((resolve, reject) => { if (zfk.isDZKFMode() || ignoreAuth) { return resolve(true); } if (typeof (zfk.pageData.downSuccess) !== 'undefined' && zfk.pageData.downSuccess.includes(id) && zfk.pageData.downSuccessUserName == zfk.getUserName()) { return resolve(true); } else if (typeof (zfk.pageData.downError) !== 'undefined' && zfk.pageData.downError.includes(id)) { return reject(false); } // BUG 不同ID导致权限混乱 // let lastTime = zfk.getGMData("lastDownScoreTime", 0); // if (zfk.now() - lastTime < 60 * 1000) { // return resolve(true); // } var username = zfk.getUserName(); if (!username) { zfk.toUserNamePage(); return; } zfk .gmAuthPost( "/yh/price/down", { id: id, key: username, }, { showErr: showErr } ) .then( (res) => { if (zfk.pageData) { if (!zfk.pageData.downSuccess) { zfk.pageData.downSuccess = [] } zfk.pageData.downSuccess.push(id) zfk.pageData.downSuccessUserName = username } // zfk.setGMData("lastDownScoreTime", zfk.now()) resolve(true); }, (err) => { if (!zfk.pageData.downError) { zfk.pageData.downError = [] } zfk.pageData.downError.push(id) reject(err); } ); }); }, alertMsg(msg, timeout = 0) { layer.open( { type: "1", content: `
    ${msg}
    `, title: "脚本提示" + (timeout == 0 ? '' : `(${(timeout / 1000).toFixed(2)}秒后自动关闭本提示})`), offset: "100px", time: timeout, btn: "关闭" }) }, tipsMsg(msg, timeout = 3000) { layer.msg(msg, { offset: "100px", time: timeout }); }, confirmMsg(msg = "请确认", option = {}) { let defConfig = { title: "脚本提示", btn: ["确定", "关闭"], fun1(index) { layer.close(index) }, fun2() { }, fun3() { } } Object.assign(defConfig, option) layer.open( { type: "1", content: `
    ${msg}
    `, title: option.title, offset: "100px", btn: defConfig.btn, yes: defConfig.fun1, btn2: defConfig.fun2, btn3: defConfig.fun3 }) }, checkLogin() { return new Promise((resolve, reject) => { if (typeof (zfk.pageData.checkLoginRes) != 'undefined') { if (zfk.pageData.checkLoginRes) { return resolve(true); } else { return reject() } } zfk.gmAuthPost("/yh/price/check").then((res) => { if (res) { zfk.pageData.checkLoginRes = true return resolve(true); } }, err => { zfk.pageData.checkLoginRes = false return reject() }); }); }, fullUrl(url, prefix = "") { if (!prefix) prefix = zfk.url.base; if (!url.startsWith("http")) { return prefix + url; } return url; }, getConfig() { // return config; let config = GM_getValue("config", {}); let def = { sjdt: "2", zdjj_min: "30", zdjj_max: "40", zdjj: "2" }; config = Object.assign(def, config); // config.courseNameMap = config.courseNameMapStr.split('\n').filter(a => a.trim()).map(a => { // let arr = a.split(' ').map(a => a.trim()) // return { name1: arr[0], name2: arr[1] } // }) return config; }, setConfig(val, site = "") { isDev && console.log("setConfig" + site, JSON.stringify(val)); // this.config = val; GM_setValue("config", val); }, fullUrl(url, prefix = "") { if (!prefix) prefix = zfk.url.base; if (!url.startsWith("http")) { return prefix + url; } return url; }, matchUrl(urlKeyword, mode = "like", url = location.href) { let res = false; switch (mode) { case "eq": res = urlKeyword == url; break; case "like": res = url.indexOf(urlKeyword) != -1; break; case "left": res = url.startsWith(urlKeyword); break; case "right": res = url.endsWith(urlKeyword); break; } return res; }, getPromiseWithAbort(p) { let obj = {}; let p1 = new Promise(function (resolve, reject) { obj.abort = reject; }); obj.promise = Promise.race([p, p1]); return obj; }, page_yhwelcome() { console.log("%c page_yhwelcome", "background:rgb(255,0,0);color:#fff"); var token = sessionStorage.getItem("token"); this.setGMData("token", token); this.setGMData("login", { login: true, time: zfk.now() }); }, gmGet(url, data) { if (isDev) console.log("gmGet", url); if (url.indexOf("?") != -1) { for (key in data) { url += `&${key}=${data[key]}`; } } else { let first = true; for (key in data) { url += (first ? "?" : "&") + `${key}=${data[key]}`; first = false; } } return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "get", url: url, data: data, headers: {}, responseType: "json", onload: function (res) { let data = res.response; if (isDev) console.log(data); resolve(data); }, onerror: function (response) { if (isDev) console.log(response); reject(response); }, }); }); }, gmPost(url, data, config = { showErr: true }) { url = zfk.fullUrl(url); if (isDev) console.log("gmPost", url); return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "post", url: url, data: JSON.stringify(data), headers: { "Content-Type": "application/json", }, responseType: "json", onload: function (res) { let data = res.response; try { if (typeof data == 'string') data = JSON.parse(data) } finally { } if (isDev) console.log(data); if (data.code != 200 && config.showErr) { layer.alert(data.message, { offset: "100px" }); return; } resolve(data); }, onerror: function (response) { if (isDev) console.log(response); reject(response); }, }); }); }, createWorker(f) { var blob = new Blob(["(" + f + ")()"]); var url = window.URL.createObjectURL(blob); var worker = new Worker(url); return worker; }, createIntervalWorker(callback, time) { var pollingWorker = zfk.createWorker(`async function (e) { setInterval(async function () { this.postMessage(null) }, ${time}) }`); pollingWorker.onmessage = callback; return pollingWorker; }, createTimeoutWorker(callback, time) { var pollingWorker = zfk.createWorker(`async function (e) { setTimeout(async function () { this.postMessage(null) }, ${time}) }`); pollingWorker.onmessage = function () { callback(); zfk.stopWorker(pollingWorker); }; return pollingWorker; }, stopWorker(vm) { try { vm && vm.terminate(); } catch (err) { console.log(err); } }, getGMData(item, def) { return GM_getValue(item, def); }, setGMData(item, val) { return GM_setValue(item, val); }, delGMData(item, val) { return GM_deleteValue(item); }, generateRandomString(length) { const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; let randomString = ""; for (let i = 0; i < length; i++) { const randomIndex = Math.floor(Math.random() * charset.length); randomString += charset.charAt(randomIndex); } return randomString; }, timeSecondsFormat(seconds) { // 确保秒数为非负整数 seconds = Math.floor(Math.abs(seconds)); // 计算小时、分钟和秒 var hours = Math.floor(seconds / 3600); var minutes = Math.floor((seconds % 3600) / 60); var secs = seconds % 60; // 如果小时、分钟或秒小于10,则在其前面添加一个0 hours = (hours < 10) ? "0" + hours : hours; minutes = (minutes < 10) ? "0" + minutes : minutes; secs = (secs < 10) ? "0" + secs : secs; // 返回格式化的时间字符串 return hours + ":" + minutes + ":" + secs; }, // 时间转换成秒 timeStringToSeconds(timeString) { if (!timeString.includes("时") && timeString.replace(/[^:]/g, '').length < 2) { timeString = '0时' + timeString } timeString = timeString .replace("小时", ":") .replace("时", ":") .replace("分钟", ":") .replace("分", ":") .replace("秒", ""); if (timeString.endsWith(":")) { timeString = timeString.substring(0, timeString.length - 1); } const parts = timeString.split(":"); if (parts.length !== 3) { if (parts.length == 2) { parts.push(0); } else { throw new Error("Invalid time string format. Expected 'hh:mm:ss'."); } } const hours = parseInt(parts[0]); const minutes = parseInt(parts[1]); const seconds = parseInt(parts[2]); if (isNaN(hours) || isNaN(minutes) || isNaN(seconds)) { throw new Error("Invalid time string format. Expected numeric values."); } return hours * 3600 + minutes * 60 + seconds; }, getLocalData(item, def) { var val = localStorage.getItem(item); if (val == null) return def; return JSON.parse(val).val; }, setLocalData(item, val) { return localStorage.setItem(item, JSON.stringify({ val: val })); }, setFormVal(selector, formVal) { $.each(formVal, function (key, val) { let $el = $(selector).find(`[name="${key}"]`); // console.log($el); // console.log(key, $el.eq(0).attr("type")); if ($el.length == 0) return true; else if ($el.length == 1) { let type = $el.eq(0).attr("type"); switch (type) { case "radio": case "checkbox": if ($el.val() == val) $el.prop("checked", true); break; default: $el.val(val); break; } } else { $el.each((i, el) => { // console.log($(el), $(el).val()); if (val.includes($(el).val())) { $(el).prop("checked", true); } }); } }); }, getFormVal(selector) { let formVal = {}; var arr = $(selector).serializeArray(); let tempArr = []; $.each(arr, function () { console.log(this); if (!tempArr.includes(this.name)) { tempArr.push(this.name); formVal[this.name] = this.value; } else { let oldVal = formVal[this.name]; if (Array.isArray(oldVal)) { formVal[this.name].push(this.value); } else { formVal[this.name] = [formVal[this.name], this.value]; } } }); return formVal; }, now() { return new Date().getTime(); }, getElByText(query, text, mode = "eq", visible = true) { let $el = null; $(query).each((i, el) => { if (visible && !$(el).is(":visible")) { return true; } if (mode == "eq" && $(el).text().trim() == text) { $el = $(el); return false; } else if ( mode == "startsWith" && $(el).text().trim().startsWith(text) ) { $el = $(el); return false; } else if (mode == "endsWith" && $(el).text().trim().endsWith(text)) { $el = $(el); return false; } }); return $el; }, getElListByText(query, text, mode = "eq", visible = true) { let arr = []; $(query).each((i, el) => { if (visible && !$(query).is(":visible")) { return true; } if (mode == "eq" && $(el).text().trim() == text) { arr.push($(el)); } else if ( mode == "startsWith" && $(el).text().trim().startsWith(text) ) { arr.push($(el)); } else if (mode == "endsWith" && $(el).text().trim().endsWith(text)) { arr.push($(el)); } }); return arr; }, random(min, max) { // 生成随机数范围 if (arguments.length === 2) { return Math.floor(min + Math.random() * (max + 1 - min)); } else { return null; } }, downloadTxt(filename, text) { var element = document.createElement("a"); element.setAttribute( "href", "data:text/plain;charset=utf-8," + encodeURIComponent(text) ); element.setAttribute("download", filename); element.style.display = "none"; document.body.appendChild(element); element.click(); document.body.removeChild(element); }, dateFormat(date = new Date(), fmt = "yyyy-MM-dd HH:mm") { let ret; if (typeof date === "number") date = new Date(date); const opt = { "y+": date.getFullYear().toString(), // 年 "M+": (date.getMonth() + 1).toString(), // 月 "d+": date.getDate().toString(), // 日 "H+": date.getHours().toString(), // 时 "m+": date.getMinutes().toString(), // 分 "s+": date.getSeconds().toString(), // 秒 // 有其他格式化字符需求可以继续添加,必须转化成字符串 }; for (let k in opt) { ret = new RegExp("(" + k + ")").exec(fmt); if (ret) { fmt = fmt.replace( ret[1], ret[1].length == 1 ? opt[k] : opt[k].padStart(ret[1].length, "0") ); } } return fmt; }, }); zfk.setGMData("version", zfk.setting.version.version); zfk.init(); if (!unsafeWindow.zfk) unsafeWindow.zfk = zfk; })();